Skip to content

Prepare for OCI publishing of helm charts to docker hub - #814

Open
janhoy wants to merge 3 commits into
apache:mainfrom
janhoy:helm-oci
Open

Prepare for OCI publishing of helm charts to docker hub#814
janhoy wants to merge 3 commits into
apache:mainfrom
janhoy:helm-oci

Conversation

@janhoy

@janhoy janhoy commented Jan 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #813

Publishes the Helm charts as OCI artifacts, alongside the existing HTTPS chart repository.

Where

oci://ghcr.io/apache/solr-operator/helm/solr-operator
oci://ghcr.io/apache/solr-operator/helm/solr
helm install solr-operator oci://ghcr.io/apache/solr-operator/helm/solr-operator --version 0.10.0
helm install example       oci://ghcr.io/apache/solr-operator/helm/solr --version 0.10.0

No helm repo add, and no credentials — public ghcr.io packages are anonymously pullable.

Why GHCR and not Docker Hub

helm push appends the chart name from Chart.yaml to the target path, and Docker Hub only supports a single namespace level. So on Docker Hub the only legal target is oci://docker.io/apache, giving apache/solr and apache/solr-operator. That would:

  • consume apache/solr for a chart, rather than leaving it for a future Solr server image, and
  • mix chart tags and image tags in one tag list on apache/solr-operator.

(The earlier oci://docker.io/apache/solr-operator-chart in this PR would have resolved to a three-level path and simply failed at push — thanks Copilot.)

ghcr.io supports nested paths, so namespacing the charts under solr-operator/helm/ keeps the chart name solr while leaving apache/solr free everywhere. Note ghcr.io/apache/* is one namespace shared by every ASF project, hence the repo-name prefix — the same thing Airflow does with ghcr.io/apache/airflow/....

Deprecation plan

Charts are published to both the OCI registry and https://solr.apache.org/charts throughout the 0.x releases. Starting with v1.0.0, charts are published to the OCI registry only. Documented in the upgrade notes and both chart READMEs.

What's in the workflow

workflow_dispatch with the two chart URLs from dist.apache.org and a dry-run flag. It never builds a chart — it re-publishes a verified copy of one that has already been released and voted on. Also used to backfill older versions.

  • Downloads keep their original basenames. The .sha512 and .prov files reference the chart's real filename, so the previous rename to solr.tgz broke sha512sum -c.
  • Downloads and pushes the .prov file, so helm install --verify works against the OCI copy. No release-tooling change needed — build_helm.sh already runs helm package --sign.
  • Verifies the detached GPG signatures against the Solr KEYS file. The checksums come from the same host as the charts, so on their own they only prove the download wasn't corrupted.
  • Authenticates with the built-in GITHUB_TOKEN + permissions: packages: write. No secrets to configure.
  • After pushing, logs out and pulls both charts back anonymously, verifying provenance and checking they're byte-identical to the released artifacts.
  • Inputs pass through the environment rather than being interpolated into the script body; azure/setup-helm is pinned to a SHA.

Other changes

  • Chart READMEs, top-level README, and the Antora docs (running-the-operator, local-tutorial, upgrade-notes) lead with OCI, keeping the HTTPS repo documented as deprecated.
  • Release wizard gains a publish_helm_charts_oci todo after the existing HTTPS publish step.
  • test_cluster.sh gains -o OCI_REGISTRY to smoke test the published OCI artifacts after a release. CRDs still come from LOCATION, since they aren't part of the OCI artifacts.

Verified

Pre-flight against ghcr.io/janhoy/*, before proposing the apache paths:

  • Nested pushes work, and a public package is fully anonymously accessible — tag list, helm show chart, and a helm pull that is byte-identical to the pushed artifact, all with no helm registry login.
  • A 2-level parent and its nested children coexist as independent packages: ghcr.io/janhoy/solr-operator, ghcr.io/janhoy/solr-operator/helm/solr-operator and ghcr.io/janhoy/solr-operator/helm/solr all resolve simultaneously. So nesting the charts under solr-operator/ does not consume ghcr.io/apache/solr-operator — it stays free for a future operator image.
  • Freshly pushed packages were private, and anonymous pull failed with 401 unauthorized at the token endpoint — which is exactly the failure the workflow's post-push anonymous re-pull is there to catch.

Needs INFRA

ghcr.io creates new packages as private. There is no self-service path to change that: .asf.yaml has no packages/registry feature, selfserve.apache.org doesn't offer it, and there's no REST endpoint (PATCH /user/packages/container/... 404s) — it's web-UI only. So an INFRA ticket is needed to make the two packages public, once per chart name; later versions inherit the visibility. ghcr.io/apache/airflow/... is existing precedent.

Not in this PR

  • Artifact Hub still indexes the HTTPS repo. Migrating it needs one repo entry per chart and would change every artifacthub.io/packages/helm/apache-solr/... URL, so it's better done as part of the v1.0.0 cutover — dual publishing keeps the current entry accurate meanwhile.
  • hack/test-upgrade.sh pins v0.2.6/v0.2.8, which exist in neither dist nor archive.apache.org (the archive starts at v0.3.0), so it can't be converted. Follow-up issue.

@janhoy
janhoy marked this pull request as draft January 14, 2026 15:57
@janhoy
janhoy requested review from Copilot and gerlowskija January 27, 2026 12:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prepares the Solr Operator project for publishing Helm charts as OCI artifacts to Docker Hub, addressing issue #813 which aims to modernize the chart distribution mechanism.

Changes:

  • Adds a GitHub Actions workflow for publishing Helm charts to Docker Hub's OCI registry with validation and verification steps
  • Updates documentation across all README files to include OCI registry installation instructions alongside traditional HTTPS repository methods
  • Integrates OCI publishing into the release wizard process as a new step after traditional Helm chart publishing

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
.github/workflows/publish-helm-oci.yaml New workflow for publishing charts to OCI registry with URL validation, checksum verification, and dry-run support
helm/solr/README.md Adds OCI registry installation and upgrade examples with traditional methods as alternatives
helm/solr-operator/README.md Restructures installation section to prioritize OCI registry approach with detailed instructions for both methods
hack/release/wizard/releaseWizard.yaml Adds new release task for OCI publishing with step-by-step instructions and verification commands
README.md Updates main README to highlight OCI registry installation as the recommended approach

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/publish-helm-oci.yaml Outdated
Comment thread helm/solr/README.md Outdated
Comment thread helm/solr-operator/README.md Outdated
Comment thread helm/solr-operator/README.md Outdated
Comment thread .github/workflows/publish-helm-oci.yaml Outdated
Comment thread helm/solr-operator/README.md Outdated
Comment thread helm/solr-operator/README.md Outdated
Comment thread hack/release/wizard/releaseWizard.yaml Outdated
Comment thread hack/release/wizard/releaseWizard.yaml Outdated
Comment thread .github/workflows/publish-helm-oci.yaml Outdated
@HoustonPutman

Copy link
Copy Markdown
Contributor

This would be awesome! And since the CRDs are in the apache release archives, I think we can do-away with the nightlies reliance all-together!

The copilot suggestions seem to be true, that it is the "apache" oci repo that we are pushing to, and it will use the name in the charts. Also I would love to not include "chart" in the name if at all possible. Obviously there might be overlap issues with the docker image (at least for the Solr-operator, not necessarily solr itself), so if not possible that's ok, but it'll be much cleaner (and keeping the same name as previous versions) if we just keep it "solr" and "solr-operator"

@HoustonPutman HoustonPutman linked an issue Mar 26, 2026 that may be closed by this pull request
@janhoy

janhoy commented Mar 27, 2026

Copy link
Copy Markdown
Contributor Author

Yes, ideally we'd have a sub-folder apache/solr-charts/solr and apache/solr-charts/solr-operator. But it seems to be quite flat after the org part, could ask INFRA. There will indeed be a collision between the image name of the solr-operator and the solr-operator-chart. That's why I first thought of using GHCR for the charts, to have a different namespace. That is still an option.

@HoustonPutman

Copy link
Copy Markdown
Contributor

I'm actually not confident there will be a conflict. I just tried it out on houstonputman/solr-operator and you can see a mix of docker images and helm charts:

https://hub.docker.com/repository/docker/houstonputman/solr-operator/general
Screenshot 2026-03-27 at 2 22 02 PM

So at least that issue should be solved.

@HoustonPutman

Copy link
Copy Markdown
Contributor

And the versions will never overlap because the images have versions that start with v and the helm charts do not. So at least we don't have to worry about that!

@HoustonPutman

HoustonPutman commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

I love the idea of automating everything, but currently the release manager has to push to docker-hub anyways. Why not just have them also push the helm chart to docker hub? The GitHub action is quite complex.

And eventually we can automate the docker build and push at the same time as automating the helm build and push.

@janhoy

janhoy commented Mar 27, 2026

Copy link
Copy Markdown
Contributor Author

And the versions will never overlap because the images have versions that start with v and the helm charts do not. So at least we don't have to worry about that!

Hmm, I hate the idea of mixing different artifact types on the same OCI path. If I do a list operation on the OCI I'd need to filter on the "^v" each time to just see the versions.

I'm leaning towards publishing helm charts on GHCR for this reason. It's a no-brainer to set it up.

I love the idea of automating everything, but currently the release manager has to push to docker-hub anyways. Why not just have them also push the helm chart to docker hub? The GitHub action is quite complex.

Mainly so not all RMs need to obtain the secret docker-hub credentials which are stored as secrets by INFRA in docker. But also good to have all these steps automated. We could use similar workflow for pushing the operator image?

@HoustonPutman

Copy link
Copy Markdown
Contributor

Hmm, I hate the idea of mixing different artifact types on the same OCI path. If I do a list operation on the OCI I'd need to filter on the "^v" each time to just see the versions.

Yeah, I had assumed that the oci tools (like ORAS) would do a much better job of differentiating artifact types for you. Apparently they do almost nothing, so unless you are looking at the tags in DockerHub, it's very confusing. I would love to have everything in one place, but I'm not against putting the charts in GHCR right now, and it doesn't stop us in the future putting them in both GHCR and DockerHub if ORAS makes differentiating the two better.

Mainly so not all RMs need to obtain the secret docker-hub credentials which are stored as secrets by INFRA in docker. But also good to have all these steps automated. We could use similar workflow for pushing the operator image?

Fair enough, I guess this is a good thing to start with, then we can expand to the image (which will be harder since multi-image build is pretty resource intensive)

@janhoy janhoy added this to the v1.0.0 milestone Apr 7, 2026
Docker Hub only supports a single namespace level, so 'helm push' (which
appends the chart name from Chart.yaml) can only produce apache/solr and
apache/solr-operator there. That burns the apache/solr name on a chart
rather than a future Solr server image, and mixes chart tags with image
tags in one tag list. The previous target, apache/solr-operator-chart,
would have resolved to a three-level path and failed at push.

ghcr.io supports nested paths, so the charts go to
ghcr.io/apache/solr-operator/helm/{solr,solr-operator}, keeping the chart
name 'solr' while leaving apache/solr free everywhere. Public ghcr.io
packages are anonymously pullable, so no credentials are needed to install.

Workflow changes beyond the registry switch:
 - Keep the downloaded basenames. The .sha512 and .prov files reference the
   chart's original filename, so renaming to solr.tgz broke 'sha512sum -c'.
 - Download and push the .prov file, so 'helm install --verify' works
   against the OCI copy.
 - Verify the detached GPG signatures against the Solr KEYS file. The
   checksums alone come from the same host as the charts.
 - Authenticate with the built-in GITHUB_TOKEN rather than Docker Hub secrets.
 - After pushing, log out and pull both charts back anonymously, checking
   they are byte-identical to the released artifacts. ghcr.io creates
   packages as private, and this is what catches that.
 - Pass inputs through the environment and pin azure/setup-helm to a SHA.

Charts are published to both the OCI registry and the deprecated HTTPS
repository throughout the 0.x releases. Starting with v1.0.0 they will be
published to the OCI registry only.

test_cluster.sh gains an -o flag to smoke test the published OCI artifacts.
Claude-Session: https://claude.ai/code/session_017UoVFe4S1qkbw4KurD77Fi
@janhoy

janhoy commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

@HoustonPutman I've rebased this on main and reworked it — proposing this as the resolution to our earlier discussion about where the charts should live.

You were right that Docker Hub can host both images and charts in one repo, with the v prefix separating the tag namespaces. My hesitation was that it makes listing awkward, and it means the chart takes the apache/solr name. Rather than argue that trade-off, GHCR sidesteps it entirely: it supports nested paths, so we get

oci://ghcr.io/apache/solr-operator/helm/solr-operator
oci://ghcr.io/apache/solr-operator/helm/solr

The chart keeps its natural name solr (which helm push takes from Chart.yaml and we can't override anyway), while apache/solr stays free on both GHCR and Docker Hub for a future Solr server image, and chart tags never mix with image tags. It also means no new secrets — the built-in GITHUB_TOKEN is enough, where Docker Hub needs credentials in CI.

I verified the mechanics against my own namespace first: nested paths work, and a public package is anonymously pullable with no helm registry login at all. Docker Hub remains an option later if we want it; nothing here forecloses that.

On the transition, I propose we cross-publish: every 0.x release goes to both the OCI registry and https://solr.apache.org/charts, so nobody has to change anything on a patch upgrade. v1.0.0 is then the first OCI-only release — a major version is the natural place to drop the old channel, and it gives users a clear, version-anchored deadline rather than a date that slips with the release schedule. That's what the upgrade notes and both chart READMEs now say. When we get to 1.0.0 we'd drop publish_helm_charts/upload_helm.sh and move the Artifact Hub entries over; I've deliberately left Artifact Hub alone for now, since migrating it would change all the existing artifacthub.io/packages/helm/apache-solr/... URLs.

One thing needing INFRA either way: ghcr.io creates new packages as private, and there's genuinely no self-service path — .asf.yaml has no packages feature, selfserve.apache.org doesn't cover it, and there isn't even a REST endpoint for it. So we'd need a ticket to flip the two packages public. It's a one-time action per chart name, and ghcr.io/apache/airflow/... is existing precedent that INFRA does this.

Does the GHCR path layout look right to you, and are you happy with 1.0.0 as the cutover?

@janhoy
janhoy marked this pull request as ready for review September 3, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish helm charts in OCI registry

3 participants